package com.leetcode.联赛.力扣杯春季编程大赛;

/**
 * @author: xiaomi
 * @date: 2021/4/5
 * @description: 2. 乐团站位
 */
public class A_2_乐团站位 {
    static A_2_乐团站位 action = new A_2_乐团站位();

    public static void main(String[] args) {
        test1();
        test2();
        test3();
        test4();
    }

    static void test1() {
        //3
        int num = 3, xPos = 0, yPos = 2;
        int res = action.orchestraLayoutByMath2(num, xPos, yPos);
        System.out.println("res = " + res);
    }

    static void test2() {
        //5
        int num = 4, xPos = 1, yPos = 2;
        int res = action.orchestraLayoutByMath2(num, xPos, yPos);
        System.out.println("res = " + res);
    }

    static void test3() {
        //3
        int num = 2511, xPos = 1504, yPos = 2235;
        int res = action.orchestraLayoutByMath2(num, xPos, yPos);
        System.out.println("res = " + res);
    }

    static void test4() {
        //1
        int num = 449572, xPos = 209397, yPos = 306801;
        int res = action.orchestraLayoutByMath(num, xPos, yPos);
        System.out.println("res = " + res);

        //
        //
        //
    }

    /**
     * 【参考了别人的剥皮的思路。】
     * 可能是第一题没有解答出来，让我第二题更加紧张了。
     * 看来我平时没有进行认真对待种下的恶果啊。
     * MD 这个思路有点复杂了，一旦出现失败的测试用例我都找不到BUG！
     *
     * @param num
     * @param xPos
     * @param yPos
     * @return
     */
    public int orchestraLayout(int num, int xPos, int yPos) {
        int width = num;
        //(xPos,xPos)
        int index = 0;
        long value = 1;
        //方向：0-右；1-下；2-左；3-上
        int direction = 0;
        int[] first = new int[]{0, 0};
        int calc = -1;
        boolean find = false;
        while (true) {
            switch (direction) {
                case 0:
                    //向右剥皮
                    if (xPos == first[0]) {
                        value += yPos - first[1];
                        find = true;
                    } else {
                        value += width;
                        calc++;
                        if ((calc & 1) == 0) {
                            width--;
                        }

                        first[0]++;
                        first[1] += width;
                    }
                    direction++;
                    break;
                case 1:
                    //向下剥皮
                    if (yPos == first[1]) {
                        value += xPos - first[0];
                        find = true;
                    } else {
                        value += width;
                        calc++;
                        if ((calc & 1) == 0) {
                            width--;
                        }

                        first[1]--;
                        first[0] += width - 1;
                    }
                    direction++;
                    break;
                case 2:
                    //向左剥皮
                    if (xPos == first[0]) {
                        value += first[0] - xPos;
                        find = true;
                    } else {
                        value += width;
                        calc++;
                        if ((calc & 1) == 0) {
                            width--;
                        }

                        first[0]--;
                        first[1] -= width;
                    }
                    direction++;
                    break;
                case 3:
                    //向上剥皮
                    if (yPos == first[1]) {
                        value += first[0] - xPos;
                        find = true;
                    } else {
                        value += width;
                        calc++;
                        if ((calc & 1) == 0) {
                            width--;
                        }

                        first[1]++;
                        first[0] -= width - 1;
                    }
                    direction = 0;
                    break;
            }
            if (find) {
                break;
            }
        }

        return (int) (value % 9);

    }

    /**
     * 当成是一个数学题
     * 居然错了。MD 我是真的讨厌矩形题目
     * 这里居然有BUG
     * 卧槽这个也会超时！
     *
     * @param num
     * @param xPos
     * @param yPos
     * @return
     */
    public int orchestraLayoutByMath(int num, int xPos, int yPos) {
        int min1 = Math.min(xPos, num - 1 - xPos);
        int min2 = Math.min(yPos, num - 1 - yPos);
        //要削去的正方形的个数
        int min = Math.min(min1, min2);
        //long value = 1;
        long value = ((((num - min) * (long) min)) << 2);
        int[] point = new int[]{min, min};
        //region    此时如果再绕圈就把自己绕晕了
//        if (xPos == min) {
//            //首先看是否同一行
//            value = value + yPos - min;
//            return (int) (value % 9);
//        } else {
//            value = value + num - min - min;
//            if (yPos == num - min - 1) {
//                value = value + xPos - min - 1;
//                return (int) (value % 9);
//            } else {
//                value = value + num - min - min - 1;
//                if (xPos == num - min - 1) {
//                    value = value + xPos - min - 1;
//                    return (int) (value % 9);
//                }
//            }
//        }
        //endregion


        int direct = 0;
        int end = num - min;
        int begin = min - 1;
        while (true) {
            if (point[0] == xPos && point[1] == yPos) {
                break;
            }
            switch (direct) {
                case 0:
                    point[1]++;
                    if (point[1] == end) {
                        //已经越界
                        point[1]--;
                        point[0]++;
                        direct++;
                    }
                    break;
                case 1:
                    point[0]++;
                    if (point[0] == end) {
                        //已经越界
                        point[0]--;
                        point[1]--;
                        direct++;
                    }
                    break;
                case 2:
                    point[1]--;
                    if (point[1] == begin) {
                        //已经越界
                        point[1]++;
                        point[0]--;
                        direct++;
                    }
                    break;
                case 3:
                    point[0]--;
                    if (point[0] == begin) {
                        //已经越界
                        point[0]++;
                        point[1]++;
                        direct = 0;
                    }
                    break;
            }
            value++;
        }

        return (int) (value % 9) + 1;
    }

    public int orchestraLayoutByMath2(int num, int xPos, int yPos) {
        int min1 = Math.min(xPos, num - 1 - xPos);
        int min2 = Math.min(yPos, num - 1 - yPos);
        //要削去的正方形的个数
        int min = Math.min(min1, min2);
        //long value = 1;
        //这个是错误的计算方式!
//        long value = ((long) (num * min - min * min) << 2) % 1000000007;
        long value = ((((num - min) * (long) min)) << 2);
        int start = min, end = num - min;
        if (xPos == start) {
            return (int) ((value + yPos - start) % 9 + 1);
        }
        if (yPos == end - 1) {
            return (int) ((value + end - start - 1 + xPos - start) % 9 + 1);
        }
        if (xPos == end - 1) {
            return (int) ((value + (end - start) * 2 - 2 + end - yPos - 1) % 9 + 1);
        }
        if (yPos == start) {
            return (int) ((value + (end - start) * 3 - 3 + end - xPos - 1) % 9 + 1);

        }
        return 0;
    }

    public int getTopLeft(int num, int xPos, int yPos) {
        int diffX = Math.min(xPos, num - 1 - xPos);
        int diffY = Math.min(yPos, num - 1 - yPos);
        return Math.min(diffX, diffY);
    }

    public int orchestraLayoutByMath3(int num, int xPos, int yPos) {
        int topLeft = getTopLeft(num, xPos, yPos);
        //先跳过topLeft个外圈
        long skip = ((long) topLeft * (num - topLeft) * 4) % 9;
//3409794320
        // 当前正方形的边长，两端点只算其中一个
        int unit = num - topLeft * 2 - 1;
        // 判断(xPos,yPos)在哪条边上
        if (topLeft == xPos) {
            //位于顶边
            skip += (yPos - topLeft);
        } else if (topLeft == num - 1 - yPos) {
            //位于右边
            skip += unit;
            skip += xPos - topLeft;
        } else if (topLeft == num - 1 - xPos) {
            //位于底边
            skip += 2 * unit;
            skip += unit + topLeft - yPos;
        } else {//位于左边
            skip += 3 * unit;
            skip += unit + topLeft - xPos;
        }
        return (int) (skip % 9) + 1;
    }
}
